One hint that a C++ class library is weakly typed is when everything is derived from a single root class, usually 'Object'. Even more telling is the implementation of the container classes (List, Stack, Set, etc): if these containers are non-templates, and if their elements are inserted/extracted as ptrs to 'Object', the container will promote weak typing. You can put an Apple into such a container, but when you get it out, the compiler only knows that it is derived from Object, so you have to do a pointer cast (a 'down cast') to cast it 'down' to an Apple (you also might hope a lot that you got it right, cause your blood is on your own head).
You can make the down cast 'safe' by putting a virtual fn into Object such as 'are_you_an_Apple()' or perhaps 'give_me_the_name_of_your_class()', but this dynamic testing is just that: dynamic. This coding style is the essence of weak typing in C++. You call a function that says 'convert this Object into an Apple or kill yourself if its not an Apple', and you've got weak typing: you don't know if the call will succeed until run-time.
When used with templates, the C++ compiler can statically validate 99% of an application's typing information (the figure '99%' is apocryphal; some claim they always get 100%, others find the need to do persistence which cannot be statically type checked). The point is: C++ gets genericity from templates, not from inheritance.